package com.silence.gankio.bluetooth

import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.*
import android.content.*
import android.media.AudioManager
import android.media.MediaPlayer
import android.net.Uri
import android.os.Bundle
import android.os.IBinder
import android.provider.Settings.Global.DEVICE_NAME
import android.support.v7.widget.LinearLayoutManager
import android.view.LayoutInflater
import android.widget.LinearLayout
import android.widget.TextView
import com.alibaba.android.arouter.facade.annotation.Route
import com.jakewharton.rxbinding2.view.RxView
import com.silence.gankio.R
import com.silence.gankio.callback.ScanBlueCallBack
import com.silence.gankio.config.Constance
import com.silence.gankio.mvvm.BaseActivity
import com.silence.gankio.mvvm.viewModel.BluetoothViewModel
import com.silence.gankio.receiver.BluetoothReceiver
import com.silence.gankio.service.MusicService
import com.silence.gankio.util.BluetoothUtil
import com.tbruyelle.rxpermissions2.RxPermissions
import com.xuexiang.rxutil2.logs.RxLog
import com.xuexiang.xui.utils.SnackbarUtils
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.xuexiang.xui.widget.dialog.strategy.impl.MaterialDialogStrategy
import kotlinx.android.synthetic.main.activity_bluetooth.*
import java.lang.reflect.InvocationTargetException
import java.util.concurrent.TimeUnit

@Route(path = Constance.ACTIVITY_URL_BLUETOOTH)
class BluetoothActivity : BaseActivity<BluetoothViewModel>() {
    override fun getModelClass(): Class<BluetoothViewModel>? = BluetoothViewModel::class.java

    override fun getActivityContent() = R.layout.activity_bluetooth

    private var player: MediaPlayer? = null
    private var bluetoothA2DP: BluetoothA2dp? = null
    private var broadcastReceiver: BroadcastReceiver? = null
    private var bluetoothReceiver: BluetoothReceiver? = null
    private var bluetoothDevice: BluetoothDevice? = null
    private val adapter by lazy { com.silence.gankio.adapter.BluetoothAdapter(null) }
    private val bluetoothUtil by lazy { BluetoothUtil() }
    private lateinit var musicControl: MusicService.MusicBinder
    private val musicConn by lazy { musicConnection() }
    private val musicService by lazy { Intent(this, MusicService::class.java) }

    @SuppressLint("CheckResult")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        initParameters()

        startService(musicService)
        bindService(musicService, musicConn, Context.BIND_AUTO_CREATE)

        setToolBarTitle("蓝牙测试")
        setBackArrow()

        RxView.clicks(btn_enable_bluetooth)
            .throttleFirst(2, TimeUnit.SECONDS)
            .compose(
                RxPermissions(this).ensure(
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION
                )
            )
            .subscribe { t ->
                run {
                    if (t) {
                        if (!bluetoothUtil.isBlueEnable()) {
                            bluetoothUtil.openBlueAsyn()
                        } else {
                            getBluetoothA2DP()
                            if (bluetoothUtil.getBluetoothAdapter().getProfileConnectionState(BluetoothHeadset.A2DP) == BluetoothHeadset.STATE_CONNECTED) {
                                MaterialDialog
                                    .Builder(this@BluetoothActivity)
                                    .title("播放音乐")
                                    .content("当前已连接蓝牙播放设备, 是否立即播放?")
                                    .positiveText("确定")
                                    .onPositive { dialog, which -> stopPlay() }
                                    .negativeText("搜索设备")
                                    .onNegative { dialog, which ->
                                        run {
//                                            disconnect()
                                            adapter.setNewData(bluetoothUtil.getBondedDevices()?.toMutableList())
                                            bluetoothUtil.scanBlue()
                                        }
                                    }
                                    .show()
                            } else {
                                adapter.setNewData(bluetoothUtil.getBondedDevices()?.toMutableList())
                                bluetoothUtil.scanBlue()
                            }
                        }
                    } else {
                        SnackbarUtils.Short(btn_enable_bluetooth, "权限获取异常， 请重试").show()
                    }
                }
            }

        btn_play_music.setOnClickListener {
            startPlay()
        }

        btn_stop_music.setOnClickListener {
            stopPlay()
        }


        recycler.layoutManager = LinearLayoutManager(this)
        recycler.adapter = adapter
        adapter.setOnItemClickListener { adapter, view, position ->
            //取消搜索
            bluetoothUtil.cancelScanBule()
            val device = adapter.data[position] as BluetoothDevice
            bluetoothDevice = device
            val bondedDevices = bluetoothUtil.getBondedDevices()
            if ((bondedDevices != null) and (bondedDevices!!.contains(device))) {
                connect()
            } else {
                createBond()
            }
        }

    }

    fun initParameters() {
        broadcastReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent?) {
                var device: BluetoothDevice
                when (intent?.action) {
                    BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED -> {
                        when (intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1)) {
                            BluetoothA2dp.STATE_CONNECTING -> {
                                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                                RxLog.e("device: ${device.name} connecting")
                            }
                            BluetoothA2dp.STATE_CONNECTED -> {
                                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                                RxLog.e("device: ${device.name} connected")

//                                //连接成功，开始播放
//                                startPlay()
                            }
                            BluetoothA2dp.STATE_DISCONNECTING -> {
                                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                                RxLog.e("device: ${device.name} disconnecting")
                            }
                            BluetoothA2dp.STATE_DISCONNECTED -> {
                                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                                RxLog.e("device: ${device.name} disconnected")
                            }
                            else -> {
                            }
                        }
                    }
                    BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED -> {
                        //<editor-fold>
                        when (intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1)) {
                            BluetoothA2dp.STATE_PLAYING -> RxLog.i("state: playing.")
                            BluetoothA2dp.STATE_NOT_PLAYING -> RxLog.i("state: not playing")
                            else -> RxLog.i("state: unkown")
                        }
                        //</editor-fold>
                    }
                    else -> {
                    }
                }
            }
        }

        bluetoothReceiver = BluetoothReceiver(object : ScanBlueCallBack {
            override fun onBluetoothBondStatus(int: Int, device: BluetoothDevice?) {
                when (int) {
                    BluetoothDevice.BOND_BONDED -> {
                        //取消搜索
                        bluetoothUtil.cancelScanBule()
                        connect()  //连接蓝牙设备
                    }
                    BluetoothDevice.BOND_BONDING -> {
                    }
                    BluetoothDevice.BOND_NONE -> {
                        //不知道是蓝牙耳机的关系还是什么原因，经常配对不成功
                        //配对不成功的话，重新尝试配对
                        createBond()
                    }
                    else -> {
                    }
                }
            }

            override fun onBluetoothStatus(int: Int) {
                when (int) {
                    BluetoothAdapter.STATE_TURNING_ON -> {
                    }
                    BluetoothAdapter.STATE_ON -> {
                        //蓝牙已打开，开始搜索并连接service
                        adapter.setNewData(bluetoothUtil.getBondedDevices()?.toMutableList())
                        bluetoothUtil.scanBlue()
                        getBluetoothA2DP()
                    }
                    BluetoothAdapter.STATE_TURNING_OFF -> {
                    }
                    BluetoothAdapter.STATE_OFF -> {
                    }
                    else -> {
                    }
                }
            }

            override fun onScanStarted() {
                SnackbarUtils.Short(nsv, "正在搜索附近的蓝牙设备...").show()
                adapter.addFooterView(LayoutInflater.from(this@BluetoothActivity).inflate(R.layout.footer_bluetooth, recycler, false))
            }

            override fun onScanFinished() {
                SnackbarUtils.Short(nsv, "设备搜索完成").show()
                adapter.removeAllFooterView()
            }

            override fun onScanning(device: BluetoothDevice) {
                RxLog.eTag(
                    "发现新设备!", "${if (device.name != null) {
                        device.name
                    } else {
                        "未知设备"
                    }} "
                )
                val deviceClassType = device.bluetoothClass.deviceClass
                //找到指定的蓝牙设备
                if ((deviceClassType == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET
                            || deviceClassType == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES)
                    && device.name == DEVICE_NAME
                ) {
                    RxLog.i("Found device:" + device.name)
                    bluetoothDevice = device
                    //start bond，开始配对
                    createBond()
                }
                RxLog.eTag("bondedDevices", device.toString())
                if (!adapter.data.contains(device)) {
                    adapter.addData(device)
                }
            }
        })


        val filter = IntentFilter()
        val blueFilter = IntentFilter()
        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)
        filter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED)
        blueFilter.addAction(BluetoothDevice.ACTION_FOUND)
        blueFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
        blueFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)
        blueFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED)
        blueFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)
        registerReceiver(broadcastReceiver, filter)
        registerReceiver(bluetoothReceiver, blueFilter)

    }

    private fun createBond() {
        RxLog.e("createBond")
        bluetoothDevice?.createBond()
    }

    //connect和disconnect都是hide方法，普通应用只能通过反射机制来调用该方法
    private fun connect() {
        RxLog.e("connect")
        if (bluetoothA2DP == null) {
            return
        }
        if (bluetoothDevice == null) {
            return
        }
        setPriority(bluetoothDevice, 100)

        try {
            val connect = BluetoothA2dp::class.java.getMethod("connect", BluetoothDevice::class.java)
            connect.invoke(bluetoothA2DP, bluetoothDevice)
        } catch (e: NoSuchMethodException) {
            RxLog.e("connect exception:$e")
            e.printStackTrace()
        } catch (e: InvocationTargetException) {
            RxLog.e("connect exception:$e")
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            RxLog.e("connect exception:$e")
            e.printStackTrace()
        } catch (e: Exception) {
            RxLog.e("$e")
            e.printStackTrace()
        }
    }

    private fun disconnect() {
        RxLog.e("disconnect")
        if (bluetoothA2DP == null) {
            return
        }

        if (bluetoothDevice == null) {
            return
        }

        setPriority(bluetoothDevice, 0)
        try {
            val disconnect = BluetoothA2dp::class.java.getMethod("disconnect", BluetoothDevice::class.java)
            disconnect.invoke(bluetoothA2DP, bluetoothDevice)
        } catch (e: Exception) {
            e.printStackTrace()
            RxLog.e("connect exception:$e")
        }

    }

    /**
     * 设置优先级
     */
    private fun setPriority(device: BluetoothDevice?, priority: Int) {
        if (bluetoothA2DP == null) {
            return
        }
        try {
            val connectMethod =
                BluetoothA2dp::class.java.getMethod("setPriority", BluetoothDevice::class.java, Int::class.java)
            connectMethod.invoke(bluetoothA2DP, device, priority)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun getBluetoothA2DP() {
        RxLog.e("getBluetoothA2DP")
        val bluetoothAdapter = bluetoothUtil.getBluetoothAdapter()

        if (bluetoothA2DP != null) {
            return
        }

        bluetoothAdapter.getProfileProxy(this, object : BluetoothProfile.ServiceListener {
            override fun onServiceDisconnected(profile: Int) {
                if (profile == BluetoothProfile.A2DP) {
                    bluetoothA2DP = null
                }
            }

            override fun onServiceConnected(profile: Int, proxy: BluetoothProfile?) {
                if (BluetoothProfile.A2DP == profile) {
                    //Service连接成功，获得BluetoothA2DP
                    bluetoothA2DP = proxy as BluetoothA2dp
                }
            }
        }, BluetoothProfile.A2DP)

    }

    private fun startPlay() {
        RxLog.e("startPlay")
        //设置最大音量
//        val audioManager: AudioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
//        val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
//        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, maxVolume, 0)
//
//        val uri: Uri = Uri.parse("android.resource://" + getPackageName() + "/" + com.silence.gankio.R.raw.music)
//
//        player = MediaPlayer()
//        player?.reset()
//
//        try {
//
//            player?.setDataSource(this, uri)
//            player?.setOnCompletionListener {
//                //播放完成，可以考虑断开连接
//                disconnect()
//            }
//            player?.setOnErrorListener { mp, what, extra ->
//                RxLog.e("Playback error.")
//                return@setOnErrorListener false
//            }
//            player?.prepare()
//            player?.start()
//
//        } catch (e: Exception) {
//            e.printStackTrace()
//
//        }



        musicControl.play()
    }

    private fun stopPlay() {
        RxLog.e("stopPlay")
//        if (player != null) {
//            player?.stop()
//            player?.release()
//            player = null
//        }

        musicControl.play()
    }

    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(broadcastReceiver)
        unregisterReceiver(bluetoothReceiver)
        unbindService(musicConn)
    }

    private inner class musicConnection: ServiceConnection {
        override fun onServiceDisconnected(name: ComponentName?) {

        }

        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            musicControl = service as MusicService.MusicBinder
        }
    }
}



